﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using DevExpress.Data;
using DevExpress.Utils;
using DevExpress.Utils.Menu;
using DevExpress.XtraBars;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Menu;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using XCI.Core;
using XCI.Data.Entity;
using XCI.Extensions;
using XCI.Helper;
using XCI.Windows.Controls;
using XCI.Windows.Plugin.GridSetting;
using XCI.Windows.Plugin.GridSetting.UI;

namespace XCI.Windows.Helper
{
    /// <summary>
    /// 表格控件操作类
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    public class GridHelper<T> where T : class, new()
    {

        private static readonly Type PageListType = typeof(PageList);
        private static readonly Type IListType = typeof(System.Collections.IList);
        private BackgroundWorker _worker;
        private Action<DoWorkEventArgs> _runAction;
        private Action<RunWorkerCompletedEventArgs> _errorAction;
        private Action<RunWorkerCompletedEventArgs> _completAction;
        private readonly Stopwatch sw = new Stopwatch();
        //private readonly LoadMask loadMask = new LoadMask();
        private bool dataLoding = false;
        private string lastSortName = string.Empty;
        private ColumnSortOrder lastSortDir = ColumnSortOrder.None;
        private Action _serviceSortingCallback;

        private readonly PageParam _pageParam = new PageParam();
        private readonly Dictionary<string, KeyValue> _changedDatas = new Dictionary<string, KeyValue>();


        /// <summary>
        /// 表格控件操作类
        /// </summary>
        /// <param name="view">表格控件</param>
        public GridHelper(GridView view) : this(view, null)
        {
        }

        /// <summary>
        /// 表格控件操作类
        /// </summary>
        /// <param name="view">表格控件</param>
        /// <param name="popup">右键擦点控件</param>
        public GridHelper(GridView view, PopupMenu popup)
        {
            string id = null;
            GridPager pager = null;
            GridControlx grid = view.GridControl as GridControlx;
            if (grid != null)
            {
                id = grid.Id;
                pager = grid.Pager;
            }
            this.Popup = popup;
            Init(id, view, pager);
        }

        /// <summary>
        /// 表格视图控件
        /// </summary>
        public GridView View { get; set; }

        /// <summary>
        /// 对象元数据
        /// </summary>
        public EntityData Metadata { get; protected set; }

        #region Set

        /// <summary>
        /// 控件标识
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// 监控列值变化
        /// </summary>
        public bool MonitorCellValueChanged { get; set; }

        /// <summary>
        /// 保留状态
        /// </summary>
        public bool IsReserveStatus { get; set; } = true;

        /// <summary>
        /// 数据为空时绘制空数据提示消息
        /// </summary>
        public bool DrawEmptyMessage { get; set; } = true;

        /// <summary>
        /// 数据为空时的空消息
        /// </summary>
        public string EmptyDataMessage { get; set; } = "暂未查到相关数据";

        /// <summary>
        /// 自动生成右键菜单
        /// </summary>
        public bool AutoPopupMenu { get; set; } = true;

        /// <summary>
        /// 分页控件
        /// </summary>
        public GridPager Pager { get; set; }

        /// <summary>
        /// 右键菜单
        /// </summary>
        public PopupMenu Popup { get; set; }

        /// <summary>
        /// 执行耗时显示控件
        /// </summary>
        public BarItem ElapsedTimeItem { get; set; }

        #endregion

        #region Calc

        /// <summary>
        /// 获取线程执行对象。
        /// </summary>
        public BackgroundWorker Worker => _worker;

        /// <summary>
        /// 选中行索引(从0开始)
        /// </summary>
        public int SelectedIndex
        {
            get
            {
                if (View.OptionsSelection.MultiSelect)//多选模式
                {
                    int[] selectedRowHandles = View.GetSelectedRows();
                    if (selectedRowHandles.Length > 0) return selectedRowHandles[0];
                    return -1;
                }
                else //单选模式
                {
                    return View.FocusedRowHandle;
                }
            }
        }

        /// <summary>
        /// 选中的主键
        /// </summary>
        public string SelectedId
        {
            get
            {
                return GetRecordId(SelectedIndex);
            }
        }

        /// <summary>
        /// 选中的对象
        /// </summary>
        public T Selected
        {
            get
            {
                return Get(SelectedIndex);
            }
        }

        /// <summary>
        /// 选中行索引数组
        /// </summary>
        public int[] SelectedIndexList
        {
            get
            {
                if (View.OptionsSelection.MultiSelect)//多选模式
                {
                    return View.GetSelectedRows();
                }
                else//单选模式
                {
                    if (View.FocusedRowHandle < 0)
                    {
                        return new int[0];
                    }
                    else
                    {
                        return new[] { View.FocusedRowHandle };
                    }
                }
            }
        }

        /// <summary>
        /// 获取勾选的主键数组
        /// </summary>
        public string[] SelectedIdList
        {
            get
            {
                var idList = new List<string>();
                foreach (var item in SelectedIndexList)
                {
                    if (item < 0) continue;
                    idList.Add(GetRecordId(item));
                }
                return idList.ToArray();
            }
        }

        /// <summary>
        /// 获取选中的对象列表
        /// </summary>
        public List<T> SelectedList
        {
            get
            {
                var list = new List<T>();
                foreach (var item in SelectedIndexList)
                {
                    if (item < 0) continue;
                    list.Add(Get(item));
                }
                return list;
            }
        }

        /// <summary>
        /// 获取勾选的主键字符串,用逗号分开
        /// </summary>
        public string SelectedIds => SelectedIdList.JoinString();

        /// <summary>
        /// 当前焦点是否是第一行
        /// </summary>
        public bool IsFirstFocus
        {
            get
            {
                if (!View.IsEmpty)
                {
                    return SelectedIndex == View.GetVisibleRowHandle(0);
                }
                return false;
            }
        }

        /// <summary>
        /// 当前焦点是否是最后一行
        /// </summary>
        public bool IsLastFocus
        {
            get
            {
                if (!View.IsEmpty)
                {
                    return SelectedIndex == View.GetVisibleRowHandle(View.RowCount - 1);
                }
                return false;
            }
        }

        /// <summary>
        /// 当前是否选中多条
        /// </summary>
        public bool HasMultiSelected
        {
            get
            {
                if (View.OptionsSelection.MultiSelect)//多选模式
                {
                    if (View.GetSelectedRows().Length > 1)
                    {
                        return true;
                    }
                    return false;
                }
                //单选模式
                return false;
            }
        }

        /// <summary>
        /// 表格中是否有数据
        /// </summary>
        public bool HasData => View.RowCount > 0;

        /// <summary>
        /// 是否单选数据
        /// </summary>
        public bool HasSingleSelected
        {
            get
            {
                if (View.OptionsSelection.MultiSelect)//多选模式
                {
                    if (View.GetSelectedRows().Length == 1)
                    {
                        return true;
                    }
                    return false;
                }
                else//单选模式
                {
                    return View.FocusedRowHandle > -1;
                }
            }
        }

        /// <summary>
        /// 是否选中数据(单选或者多选)
        /// </summary>
        public bool HasSelected
        {
            get
            {
                if (View.OptionsSelection.MultiSelect)//多选模式
                {
                    return View.GetSelectedRows().Length > 0;
                }
                //单选模式
                return View.FocusedRowHandle > -1;
            }
        }

        /// <summary>
        /// 是否有数据被修改
        /// </summary>
        public bool HasDataChanged => _changedDatas.Count > 0;

        /// <summary>
        /// 分页参数
        /// </summary>
        public PageParam Paged
        {
            get
            {
                _pageParam.Clear();
                if (Pager != null)
                {
                    _pageParam.PageIndex = Pager.PageIndex;
                    _pageParam.PageSize = Pager.PageSize;
                }
                if (View.SortInfo.Count > 0)
                {
                    var sortInfo = View.SortInfo[0];
                    var sname = sortInfo.Column.FieldName;
                    _pageParam.SortName = sname;
                    _pageParam.SortDir = sortInfo.SortOrder == ColumnSortOrder.Ascending ? "asc" : "desc";
                }
                return _pageParam;
            }
        }

        /// <summary>
        /// 数据加载耗时
        /// </summary>
        public TimeSpan WorkElapsedTime { get; private set; }

        #endregion

        #region 公共事件

        /// <summary>
        /// 修改数据事件
        /// </summary>
        public event EventHandler<EventArgs> ModifyData;
        protected void OnModifyData(EventArgs e)
        {
            ModifyData?.Invoke(this, e);
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="id">控件标识</param>
        /// <param name="view">视图控件</param>
        /// <param name="pager">分页控件</param>
        private void Init(string id, GridView view, GridPager pager)
        {
            this.Id = id;
            this.View = view;
            this.Pager = pager;

            if (View == null) throw new ArgumentNullException(nameof(View));
            this.Metadata = EntityHelper.Get(typeof(T));

            #region GridSettingPlugin

            InitSettingPlugin();

            #endregion

            #region CustomDrawRowIndicator
            if (View.OptionsView.ShowIndicator)
            {
                View.CustomDrawRowIndicator += (o, e) =>
                {
                    if (e.Info.IsRowIndicator && e.RowHandle >= 0)
                    {
                        e.Info.DisplayText = (e.RowHandle + 1).ToString();
                        e.Info.ImageIndex = -1;
                    }
                };
            }
            #endregion

            #region CustomDrawEmptyForeground
            view.CustomDrawEmptyForeground += (o, e) =>
            {
                if (dataLoding || view.RowCount > 0) return;
                if (DrawEmptyMessage)
                {
                    //字体
                    Font f = new Font(AppearanceObject.DefaultFont.Name, 16, FontStyle.Regular);
                    //显示位置
                    Rectangle r = new Rectangle(view.GridControl.Width / 2 - 100, e.Bounds.Top + 45, e.Bounds.Right - 5, e.Bounds.Height - 5);
                    //显示颜色
                    e.Cache.DrawString(EmptyDataMessage, f, e.Cache.GetSolidBrush(Color.Gray), r);
                }
            };
            #endregion

            #region MouseUp

            View.MouseUp += (o, e) =>
            {
                if (Popup != null)
                {
                    GridHitInfo hi = View.CalcHitInfo(e.Location);
                    if (e.Button == MouseButtons.Right
                     && (hi.HitTest == GridHitTest.EmptyRow
                         || hi.HitTest == GridHitTest.Row
                         || hi.HitTest == GridHitTest.RowCell))
                    {
                        Popup.ShowPopup(Control.MousePosition);
                    }
                }
            };

            #endregion


            //#region BarControllerFont

            //var menuManager = View.GridControl.MenuManager;
            ////设置菜单字体样式
            //var barManager = (BarManager)menuManager;
            //if (barManager?.Controller != null)
            //{
            //    barManager.Controller.PropertiesBar.LargeIcons = WindowsSetting.Instance.PageToolbarLargeIcons;
            //    barManager.Controller.PropertiesBar.LargeIconsInMenu = DefaultBoolean.False;
            //}

            //#endregion

            #region AutoBuildPopupMenu

            AutoBuildPopupMenuCore();

            #endregion

            #region MonitorCellValueChanged

            if (MonitorCellValueChanged)
            {
                View.CellValueChanged += View_CellValueChanged;
            }

            #endregion

            #region Worker
            InitWorker();
            #endregion
        }

        /// <summary>
        /// 设置服务端排序数据加载回调函数
        /// </summary>
        /// <param name="serviceSortingCallback">数据加载回调函数</param>
        public void ServiceSorting(Action serviceSortingCallback)
        {
            _serviceSortingCallback = serviceSortingCallback;
            View.Columns.ForEach(p => p.SortMode = ColumnSortMode.Custom);

            View.EndSorting += (o, e) =>
            {
                var sorts = View.SortInfo;
                if (sorts.Count > 0)
                {
                    var sortName = sorts[0].Column.FieldName;
                    var sortDir = sorts[0].SortOrder;
                    if (sortName.IsNotEmpty() && sortName.Equals(lastSortName) && sortDir.Equals(lastSortDir))
                    {
                        return;
                    }
                    else
                    {
                        lastSortName = sortName;
                        lastSortDir = sortDir;
                    }
                }
                _serviceSortingCallback?.Invoke();
            };

            View.CustomColumnSort += (o, e) =>
            {
                e.Handled = true;
                e.Result = Comparer.Default.Compare(e.Value1, e.Value2);
            };
        }

        private void InitWorker()
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = false;
            _worker.WorkerSupportsCancellation = false;
            _worker.DoWork += Worker_DoWork;
            _worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            dataLoding = true;
            sw.Reset();
            sw.Start();
            _runAction?.Invoke(e);
            sw.Stop();
            WorkElapsedTime = sw.Elapsed;
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                if (_errorAction != null)
                {
                    _errorAction?.Invoke(e);
                }
                else
                {
                    //loadMask.Hide();
                    View.HideLoadingPanel();
                    MessageBoxHelper.ShowError(DebugHelper.BuildAllMessage(e.Error));
                }
            }
            else
            {
                if (ElapsedTimeItem != null)
                {
                    ElapsedTimeItem.Caption = $"耗时:{WorkElapsedTime.TotalMilliseconds:###0.##} ms";
                }
                SetDataSource(e.Result);
                _completAction?.Invoke(e);
            }
            dataLoding = false;
            //loadMask.Hide();
            View.HideLoadingPanel();
        }

        /// <summary>
        /// 设置异步执行回调函数
        /// </summary>
        /// <param name="runAction">回调函数</param>
        public GridHelper<T> RunCallback(Action<DoWorkEventArgs> runAction)
        {
            _runAction = runAction;
            return this;
        }

        /// <summary>
        /// 设置后台操作异常回调函数。
        /// </summary>
        /// <param name="errorAction">回调函数</param>
        public GridHelper<T> ErrorCallback(Action<RunWorkerCompletedEventArgs> errorAction)
        {
            _errorAction = errorAction;
            return this;
        }

        /// <summary>
        /// 设置后台操作已完成、 已取消或引发异常时回调函数。
        /// </summary>
        /// <param name="completAction">回调函数</param>
        public GridHelper<T> CompletCallback(Action<RunWorkerCompletedEventArgs> completAction)
        {
            _completAction = completAction;
            return this;
        }

        /// <summary>
        /// 开始执行后台操作。
        /// </summary>
        public void RunAsync()
        {
            if (_worker.IsBusy)
            {
                return;
            }
            //if (loadMaskDelay > -1)
            //{
            //    loadMask.Show(View?.GridControl, loadMaskDelay);
            //}
            View.ShowLoadingPanel();
            _worker.RunWorkerAsync();
        }

        /// <summary>
        /// 请求取消的挂起的后台操作。
        /// </summary>
        public void CancelAsync()
        {
            if (_worker.IsBusy)
            {
                _worker.CancelAsync();
            }
        }

        /// <summary>
        /// 自动生成右键菜单
        /// </summary>
        private void AutoBuildPopupMenuCore()
        {
            if (AutoPopupMenu == false) return;
            if (Popup != null) return;
            var menuManager = View.GridControl.MenuManager;
            if (menuManager == null) return;

            Popup = new PopupMenu();
            Popup.Manager = (BarManager)menuManager;
            foreach (BarItem item in Popup.Manager.Items)
            {
                if (!(item is BarButtonItem)) continue;
                Popup.ItemLinks.Add(item);
            }
        }

        /// <summary>
        /// 初始化配置菜单
        /// </summary>
        private void InitSettingPlugin()
        {
            if (string.IsNullOrEmpty(Id)) return;
            var data = GridSettingManager.Instance.LoadSetting(Id);
            SetSetting(data);
            if (string.IsNullOrEmpty(data))
            {
                AutoBuildColumn();
            }
            View.PopupMenuShowing += (s, e) =>
            {
                if (e.MenuType != GridMenuType.Column) return;
                var menu = e.Menu as GridViewColumnMenu;
                if (menu == null) return;

                //DXMenuItem customItem = new DXMenuItem("保存配置", (oo, aa) =>
                //{
                //    GridSettingManager.SaveSetting(view.Id, view.GetSetting());
                //});
                //customItem.BeginGroup = true;
                //menu.Items.Add(customItem);

                if (Sys.SysRuntime.Setting.AllowGridSetting)
                {
                    var customItem = new DXMenuItem("表格配置", (o, a) => ShowSettingForm(),
                        XCI.Sys.Properties.Resources.technology_16x16);
                    customItem.BeginGroup = true;
                    menu.Items.Add(customItem);
                }
            };
        }

        /// <summary>
        /// 显示配置窗口
        /// </summary>
        public void ShowSettingForm()
        {
            var settingFrm = new GridConfigForm();
            settingFrm.Initialize(new Plugin.GridSetting.GridSettingPlugin(View, Id, Metadata));
            settingFrm.ShowDialog();
            settingFrm.Dispose();
        }

        /// <summary>
        /// 数据导出
        /// </summary>
        public void Export()
        {
            View.ShowRibbonPrintPreview();
        }

        /// <summary>
        /// 删除选中的数据
        /// </summary>
        public void Delete(Action action, string confirmMsg = null)
        {
            int count = View.GetSelectedRows().Length;
            if (count == 0)
            {
                MessageBoxHelper.ShowError("请至少选中一条数据");
                return;
            }
            if (string.IsNullOrEmpty(confirmMsg))
            {
                confirmMsg = $"确定要删除选中的 {count} 条数据吗?";
            }
            if (MessageBoxHelper.ShowWarnYesNo(confirmMsg) != DialogResult.Yes)
            {
                return;
            }

            action?.Invoke();
        }

        /// <summary>
        /// 修改状态确认
        /// </summary>
        public void StatusConfirm(string type, Action action)
        {
            int count = View.GetSelectedRows().Length;
            if (count == 0)
            {
                MessageBoxHelper.ShowError("请至少选中一条数据");
                return;
            }
            var confirmMsg = $"确定要{type}选中的 {count} 条数据吗?";
            if (MessageBoxHelper.ShowWarnYesNo(confirmMsg) != DialogResult.Yes)
            {
                return;
            }

            action?.Invoke();
        }

        /// <summary>
        /// 根据列信息获取行索引
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="columnValue">列值</param>
        public int GetRowIndexByColumn(string columnName, string columnValue)
        {
            for (int i = 0; i < View.DataRowCount; i++)
            {
                var value = View.GetRowCellValue(i, columnName);
                if (value.ToStringOrEmpty().Equals(columnValue.ToStringOrEmpty()))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 获取选中行的最后一行索引
        /// </summary>
        private int GetLastSelectedRowIndex()
        {
            var sz = View.GetSelectedRows();
            int count = sz.Length;
            if (count > 0)
            {
                return sz[count - 1];
            }
            return -1;
        }

        /// <summary>
        /// 选中单行
        /// </summary>
        /// <param name="rowIndex">行索引</param>
        public void SelectSingleRow(int rowIndex)
        {
            View.FocusedRowHandle = rowIndex;
            View.SelectRow(rowIndex);
            View.MakeRowVisible(rowIndex);
        }

        /// <summary>
        /// 清除选中的行
        /// </summary>
        public void ClearSelectRow()
        {
            View.ClearSelection();
            View.FocusedRowHandle = -1;
        }

        /// <summary>
        /// 转到指定页
        /// </summary>
        /// <param name="pageIndex">页码</param>
        public void GotoPage(int pageIndex)
        {
            if (Pager == null)
            {
                throw new System.ArgumentNullException("Pager", "请先指定分页控件");
            }
            Pager.GotoPage(pageIndex);
        }

        /// <summary>
        /// 设置分页大小
        /// </summary>
        /// <param name="pageSize">分页大小</param>
        public void SetPageSize(int pageSize)
        {
            if (Pager == null)
            {
                throw new System.ArgumentNullException("Pager", "请先指定分页控件");
            }
            Pager.PageSize = pageSize;
        }

        /// <summary>
        /// 设置页码
        /// </summary>
        /// <param name="pageIndex">页码</param>
        public void SetPageIndex(int? pageIndex)
        {
            if (Pager == null)
            {
                throw new System.ArgumentNullException("Pager", "请先指定分页控件");
            }
            Pager.SetPageIndex(pageIndex);
        }

        /// <summary>
        /// 双击表格行
        /// </summary>
        public void DblClickRow(EventArgs e, Action editAction)
        {
            if (!(e is DXMouseEventArgs ev)) return;

            GridHitInfo info = View.CalcHitInfo(ev.Location);
            if (ev.Clicks == 2 && ev.Button == MouseButtons.Right)
            {
                return;
            }
            if (editAction != null
                && ev.Clicks == 2
                && (info.HitTest == GridHitTest.Row || info.HitTest == GridHitTest.RowCell)
                && View.FocusedRowHandle > -1)
            {
                editAction();
            }
        }

        /// <summary>
        /// 获取表格配置
        /// </summary>
        public string GetSetting()
        {
            return WinHelper.GetGridViewSetting(View);
        }

        /// <summary>
        /// 应用表格配置
        /// </summary>
        public void SetSetting(string setting)
        {
            WinHelper.SetGridViewSetting(View, setting);
        }

        /// <summary>
        /// 设置数据源
        /// </summary>
        /// <param name="dataSource">数据源</param>
        public void SetDataSource(object dataSource)
        {
            if (View.GridControl == null) return;
            if (dataSource == null)
            {
                View.GridControl.DataSource = null;
                return;
            }
            IEnumerable listDataSource;
            var dataType = dataSource.GetType();
            if (dataType.IsGenericType && dataType.BaseType == PageListType)
            {
                var pd = (PageList<T>)dataSource;
                if (Pager != null) this.Pager.TotalCount = pd.Total;
                listDataSource = pd.Rows;
            }
            else if (dataType.IsGenericType && dataType.BaseType == IListType)
            {
                listDataSource = (System.Collections.IList)dataSource;
            }
            else
            {
                listDataSource = (IEnumerable)dataSource;
            }

            if (IsReserveStatus && View.GridControl.DataSource != null)
            {
                var source = ((System.Collections.IList)View.GridControl.DataSource);
                source.Clear();
                foreach (var item in listDataSource)
                {
                    source.Add(item);
                }
                View.GridControl.RefreshDataSource();
            }
            else
            {
                View.GridControl.DataSource = listDataSource;
            }
        }

        ///// <summary>
        ///// 设置数据源
        ///// </summary>
        ///// <param name="dataSource">数据源</param>
        //public void SetDataSource(PageList<T> dataSource)
        //{
        //    if (Pager != null)
        //    {
        //        this.Pager.TotalCount = dataSource.Total;
        //    }
        //    SetDataSource(dataSource.Rows);
        //}

        /// <summary>
        /// 获取指定行的对象
        /// </summary>
        /// <param name="rowHandle">行索引号</param>
        public T Get(int rowHandle)
        {
            if (rowHandle < 0) return default;

            var rowObject = View.GetRow(rowHandle);
            return rowObject as T;
            //var view = rowObject as DataRowView;
            //if (view == null) return rowObject as T;
            //var instance = new T();
            //DataTableHelper.ConvertToObject(view.Row, () => instance);
            //return instance;
        }

        /// <summary>
        /// 获取主键值
        /// </summary>
        /// <param name="rowHandle">行索引</param>
        public string GetRecordId(int rowHandle)
        {
            if (rowHandle < 0) return string.Empty;

            string keyName = Metadata.PrimaryProperty.Name;
            if (string.IsNullOrEmpty(keyName))
            {
                throw new ArgumentException("请指定KeyFieldName属性,主键名不能为空");
            }
            return View.GetRowCellValue(rowHandle, keyName).ToStringOrEmpty();
        }

        /// <summary>
        /// 选中指定的行
        /// </summary>
        /// <param name="rowIndex">序号</param>
        public void SelectRowByIndex(int rowIndex)
        {
            if (rowIndex > -1)
            {
                View.SelectRow(rowIndex);
                View.FocusedRowHandle = rowIndex;
            }
        }

        /// <summary>
        /// 选中行使用主键
        /// </summary>
        /// <param name="id">主键</param>
        public void SelectRowById(string id)
        {
            if (id.IsEmpty()) return;
            var rowIndex = GetRowIndexById(id);
            SelectRowByIndex(rowIndex);
        }

        /// <summary>
        /// 根据主键获取行索引
        /// </summary>
        /// <param name="id">主键</param>
        public int GetRowIndexById(string id)
        {
            if (id == null) return -1;
            for (int i = 0; i < View.DataRowCount; i++)
            {
                var pkValue = View.GetRowCellValue(i, Metadata.PrimaryProperty.Name);
                if (pkValue.ToString().Equals(id))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 自动生成列
        /// </summary>
        public void AutoBuildColumn()
        {
            WinHelper.AutoBuildGridColumn(View, Metadata);
        }

        /// <summary>
        /// 当简拼按上下方向键时移动焦点行
        /// </summary>
        public void OnUpDownMoveFocusRow(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
            {
                View.MovePrev();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Down)
            {
                View.MoveNext();
                e.Handled = true;
            }
        }

        public void OnServerStartSorting()
        {
            View.GridControl.DataSource = null;
        }

        #region DataChanged

        /// <summary>
        /// 添加改变的列值
        /// </summary>
        /// <param name="id">主键</param>
        /// <param name="item">改变项</param>
        private void AddDataChanged(string id, KeyValue item)
        {
            if (string.IsNullOrEmpty(id)) return;
            _changedDatas[id] = item;
        }

        /// <summary>
        /// 获取改变的数据
        /// </summary>
        public Dictionary<string, KeyValue> GetChangedDatas()
        {
            View.PostEditor();
            return _changedDatas;
        }

        /// <summary>
        /// 获取改变的数据
        /// </summary>
        public List<PrimaryKeyValue> GetChangedDataList()
        {
            View.PostEditor();
            var list = new List<PrimaryKeyValue>();
            foreach (var item in _changedDatas)
            {
                list.Add(new PrimaryKeyValue(item.Key, item.Value.Key, item.Value.Value));
            }
            return list;
        }

        /// <summary>
        /// 清空变化的值列表
        /// </summary>
        public void ClearDataChanged()
        {
            _changedDatas.Clear();
        }

        private void View_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.RowHandle <= -1 || Metadata == null || string.IsNullOrEmpty(Metadata.PrimaryProperty.Name)) return;
            string columnName = e.Column.FieldName;
            string pk = View.GetRowCellValue(e.RowHandle, Metadata.PrimaryProperty.Name).ToStringOrEmpty();
            if (string.IsNullOrEmpty(pk)) return;
            string columnValue = e.Value.ToStringOrEmpty();
            AddDataChanged(pk, new KeyValue(columnName, columnValue));
            OnModifyData(EventArgs.Empty);
        }

        #endregion

        #endregion
    }
}